#include "../../include/rs_485/485_common.h"
/*-------------------------------------------
*
Author:wnc
v1.0 start to use version to manageme the code
1.send data: ./ts_uart s send.txt 
2.recv data: ./ts_uart r
Modified by mtd at 20240411
*
----------------------------------------------*/
#define UART_NAME "/dev/ttyS0"
int main(int argc, char **argv) {
	int i = 0, rd = 0;
	fd_set readFds;
	int retval;
	unsigned int count = 0;
	int mctrl = 0x8000; //TIOCM_LOOP;
	struct timeval respTime;
	unsigned char input_buf[bufsize], output_buf[bufsize];
	unsigned long long size = 0;
	int sendsize, sleeptime=0;
	int j,error=0;

	ut.baudrate=9600;  //argv[3]
	ut.flow_cntrl=0;  //argv[4]
	ut.max_delay=0;  //argv[5]
	ut.random_enable=0; //argv[6]
	// ut.fd = open(UART_DEV_NAME, O_RDWR);

	if(argv[2] == NULL){
		ut.fd = open(UART_NAME, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK );
	}else{
		ut.fd = open(UART_NAME, O_RDWR);
	}  
  

	if (ut.fd == -1) {
		printf("open_port: Unable to open port - %s ", argv[7]);
		exit(1);
	} else
		fcntl(ut.fd, F_SETFL, 0);
    
	printf("Existing port baud=%d \n", getbaud(ut.fd));
	/* save current port settings */
	tcgetattr(ut.fd, &oldtio);
	initport(ut.fd, ut.baudrate, ut.flow_cntrl);
	printf("Configured port for New baud=%d\n", getbaud(ut.fd));

	sscanf(argv[1],"%c",&tx_rx);

	//disable loopback mode
	mctrl = 0x0000; //TIOCM_LOOP;
	ioctl(ut.fd, 0x5418, &mctrl);  //TIOCMSET

	switch (tx_rx) {
		case 't':
			printf("enter uart test mode\n");
			while(1) {
	
				sleep(1);
			}
		case 'r':
			read_flag = 0;
			while(1){
				FD_ZERO(&readFds);
				FD_SET(ut.fd, &readFds);
				respTime.tv_sec =  10;
				respTime.tv_usec = 0;

				/* Sleep for command timeout and expect the response to be ready. */
				retval = select(FD_SETSIZE, &readFds, NULL, NULL, &respTime);
				if (retval == 0 ) {
					if (read_flag == 0) {
						printf("\n Waited until timeout; no data was available to read. Exiting... \n");
						if (unlink(argv[2]) == -1)
							printf("\n Failed to delete the file %s \n",argv[2]);
						    close_port();
					    }
					    else {
							//printf("\n select() timed out... waiting for more data\n");
						    continue; /*skip this loop because FD_SET doesn't have any data */
					    }
				}
				else if(retval == ERROR)
					printf("\n select: error :: %d\n",retval);
        		        /* Read data, abort if read fails. */
				if(FD_ISSET(ut.fd, &readFds) != 0)  {
					//fcntl(ut.fd, F_SETFL, FNDELAY);
				    /*	printf("\n entering readport func \n"); */
					if(read_flag == 0) {
						gettimeofday(&ut.start_time, NULL);			
						read_flag = 1;
						printf("\n Reading data from port to file...\n");
					}
					rd = readport(&ut.fd, output_buf);
					if (ERROR == rd) {
						printf("Read Port failed\n");
						close_port();
					}
					printf("************************************************************************************************* \n");
					printf("Recv data output_buf:  %s\n", output_buf);
					printf("************************************************************************************************* \n");
				}
#if 1
				for (i = 0; i < rd; i++) {
					if (output_buf[i] != 0x55) {
						count++;
						//printf("error[%d] is %02x\n", i, output_buf[i]);
						//printf("data[%d] is %c\n", i, output_buf[i]);
					}
				}
#endif
				size += rd;
				//i = writeport(&ut.fd, output_buf, rd);
				if (rd != 0)
					printf("Read %d bytes from port , total data:%d total:%lld\n",rd, count, size);

				memset(output_buf, 0, bufsize);
			}
			gettimeofday(&ut.end_time,NULL);
			printf("\n Read %lld bytes from port data:%d \n",size, count);
			FD_CLR(ut.fd, &readFds);	
			break;


		case 's':
			fd1 = open(argv[2],O_RDONLY);
			if(fd1 == -1) {
				printf("\n cannot open %s \n",argv[2]);
			}

			printf("\n Sending data from file to port...\n");
			gettimeofday(&ut.start_time,NULL);
			
			while(1) {
				if (ut.random_enable != 0)
					sendsize = get_rand_value(bufsize);
				else
					sendsize = bufsize;

				if (fd1 > 0) {
					rd = read(fd1, &input_buf, sendsize);
					if(rd == 0)
						 break;
				} else {
					memset(input_buf, 0x55, sendsize);
					rd = sendsize;
				}
				printf("\n Read from input file %d bytes \n",rd);
				printf("\n print array addr:%p--%p--%p--%p\n",&input_buf,&input_buf[1],&input_buf[2],&input_buf[3]);

				FD_ZERO(&readFds);
				FD_SET(ut.fd, &readFds);
				respTime.tv_sec =  10;
				respTime.tv_usec = 0;
				fcntl(ut.fd, F_SETFL, 0);
				/* Sleep for command timeout and expect the response to be ready. */
				retval = select(FD_SETSIZE, NULL, &readFds, NULL, &respTime);
				if (retval == 0 ) {
					printf("\n Waited tx until timeout... \n");
					while(1) {
						sleep(10);
					}
				}
				else if (retval == ERROR)
					printf("\n select: error :: %d\n",retval);
	
        		        /* Read data, abort if read fails. */
				if(FD_ISSET(ut.fd, &readFds) != 0)  {
					if (!writeport(&ut.fd, input_buf, rd)) {
						printf("\n Writing to port failed\n");
						close_port();
					} else
						size += rd;
				}

				#ifdef ANDROID_FS
				/* tcdrain not available on ANDROID */
				ioctl(ut.fd, TCSBRK, 1); //equivalent to tcdrain(). perhaps permanent replacement?
				#else
				if(ERROR == tcdrain(ut.fd))
					printf("\n tcdrain failure \n");
				#endif
				memset(input_buf,0,bufsize);

				if (ut.max_delay) {
					sleeptime = get_rand_value(ut.max_delay);
					printf("\n Sleeping for %u seconds...\n",sleeptime);
					sleep(sleeptime); /*sleep for a maximum of X random secs */
					system("echo 1 > /sys/devices/platform/serial8250.0/uart1_rts_toggle");
				}
				if (fd1 <= 0)
					break;
			}
			gettimeofday(&ut.end_time,NULL);
			printf("\n Written %lld bytes to port \n",size);
			/* Wait for 5 seconds for Transmitting to complete before sending the Break sequence */
			sleep(1);
			break;

		case 'm':
			//set loopback mode
			mctrl = 0x8000;
			ioctl(ut.fd, 0x5418, &mctrl);  //TIOCMSET

			fd1 = open(argv[2], O_RDONLY);
			if(fd1 == -1) {
				printf("\n cannot open %s \n",argv[2]);
				for (i = 0; i < bufsize; i++)
					input_buf[i] = i % 256;	
				rd = bufsize;
			} else {
				rd = read(fd1, &input_buf, bufsize);
			}

			printf("Read %d bytes data from file\n", rd);
			printf("Sending data from file to port...\n");

			gettimeofday(&ut.start_time, NULL);

			size = 0;		

			while(1) {
				if (ut.random_enable != 0)
					sendsize = get_rand_value(bufsize);
				else
					sendsize = bufsize;


				if (sendsize >= rd || sendsize <= 0)
					sendsize = rd - 1;
				
				fcntl(ut.fd, F_SETFL, 0);
				if (!writeport(&ut.fd, input_buf, sendsize)) {
					printf("\n Writing to port failed %d\n", sendsize);
					close_port();
				}

				i = 0;
				j = 0;
				while(j < sendsize) {

				 	FD_ZERO(&readFds);
					FD_SET(ut.fd, &readFds);
					respTime.tv_sec =  5;
					respTime.tv_usec = 0;
	
					/* Sleep for command timeout and expect the response to be ready. */
					retval = select(FD_SETSIZE, &readFds, NULL, NULL, &respTime);
					if (retval == 0 ) {
						printf("\n Waited until timeout: send:%d, receive:%d\n", sendsize, j);
						while(1) {
							sleep(10);
						}
					}
					else if (retval == ERROR)
						printf("\n select: error :: %d\n",retval);
	
				        /* Read data, abort if read fails. */
					if(FD_ISSET(ut.fd, &readFds) != 0)  {
						i = read(ut.fd, output_buf + j, rd - j);
						j += i;
					}
				}
				size += sendsize;
				printf("send:%d, receive:%d total:%lld\n", sendsize, j, size);
				i = 0;
				if(j >= sendsize) {
					while(j--) {
						if(output_buf[j] != input_buf[j])
								i = j;
					}
										
				} else {
					printf("send != receive\n");
					while(1) {
						sleep(10);
					}
				}
				
				if(i > 0) {
					printf("+++++++position:%d  src:%02x but dst:%02x\n", i-5, input_buf[i-5], output_buf[i-5]);
					printf("+++++++position:%d  src:%02x but dst:%02x\n", i-4, input_buf[i-4], output_buf[i-4]);
					printf("+++++++position:%d  src:%02x but dst:%02x\n", i-3, input_buf[i-3], output_buf[i-3]);
					printf("+++++++position:%d  src:%02x but dst:%02x\n", i-2, input_buf[i-2], output_buf[i-2]);
					printf("+++++++position:%d  src:%02x but dst:%02x\n", i-1, input_buf[i-1], output_buf[i-1]);
					printf("+++++++position:%d  src:%02x but dst:%02x\n", i, input_buf[i], output_buf[i]);
					printf("+++++++position:%d  src:%02x but dst:%02x\n", i+1, input_buf[i+1], output_buf[i+1]);
					printf("+++++++position:%d  src:%02x but dst:%02x\n", i+2, input_buf[i+2], output_buf[i+2]);
					printf("+++++++position:%d  src:%02x but dst:%02x\n", i+3, input_buf[i+3], output_buf[i+3]);
					printf("+++++++position:%d  src:%02x but dst:%02x\n", i+4, input_buf[i+4], output_buf[i+4]);
					printf("+++++++position:%d  src:%02x but dst:%02x\n", i+5, input_buf[i+5], output_buf[i+5]);
					printf("+++++++position:%d  src:%02x but dst:%02x\n", i+6, input_buf[i+6], output_buf[i+6]);
					
					while(1) {
						sleep(10);
					}
					//close_port();
				}
				//memset(input_buf, 0, bufsize);
				memset(output_buf, 0, bufsize);
			}

			//disable loopback mode
			mctrl = 0x0000; //TIOCM_LOOP;
			ioctl(ut.fd, 0x5418, &mctrl);  //TIOCMSET
			close(fd1);
			gettimeofday(&ut.end_time,NULL);

			break;
	}

	timersub(&ut.end_time,&ut.start_time,&ut.diff_time);
	if(tx_rx == 'r')	
		 ut.diff_time.tv_sec -= 5;
        printf("\n Time taken %08ld sec, %08ld usec\n\n ",ut.diff_time.tv_sec,ut.diff_time.tv_usec);
        /* restore th old port settings. */
	close_port();
	return 0;
}


